using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace RedRiver.Framework.XtraCommon.FastReflection{
    public class AttributeFactory{
        private readonly Func<object> _attributeCreator;
        private readonly List<Action<object>> _propertySetters;

        public AttributeFactory(CustomAttributeData data){
            Data = data;

            var ctorInvoker = new ConstructorInvoker(data.Constructor);
            object[] ctorArgs = data.ConstructorArguments.Select(a => a.Value).ToArray();
            _attributeCreator = () => ctorInvoker.Invoke(ctorArgs);

            _propertySetters = new List<Action<object>>();
            if (data.NamedArguments != null){
                foreach (CustomAttributeNamedArgument arg in data.NamedArguments){
                    var property = (PropertyInfo) arg.MemberInfo;
                    var propertyAccessor = new PropertyAccessor(property);
                    object value = arg.TypedValue.Value;
                    _propertySetters.Add(o => propertyAccessor.SetValue(o, value));
                }
            }
        }

        public CustomAttributeData Data{
            get;
            private set;
        }

        public Attribute Create(){
            object attribute = _attributeCreator();

            foreach (var setter in _propertySetters){
                setter(attribute);
            }

            return (Attribute) attribute;
        }
    }
}